package com.luck.picture.lib.shootbutton;

import android.Manifest;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.ImageFormat;
import android.graphics.Matrix;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.SurfaceTexture;
import android.hardware.camera2.CameraAccessException;
import android.hardware.camera2.CameraCaptureSession;
import android.hardware.camera2.CameraCharacteristics;
import android.hardware.camera2.CameraDevice;
import android.hardware.camera2.CameraManager;
import android.hardware.camera2.CameraMetadata;
import android.hardware.camera2.CaptureRequest;
import android.hardware.camera2.TotalCaptureResult;
import android.hardware.camera2.params.StreamConfigurationMap;
import android.media.Image;
import android.media.ImageReader;
import android.media.MediaRecorder;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.HandlerThread;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
import androidx.core.app.ActivityCompat;
import androidx.appcompat.app.AppCompatActivity;
import android.util.Log;
import android.util.Size;
import android.util.SparseIntArray;
import android.view.MotionEvent;
import android.view.Surface;
import android.view.TextureView;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;
import android.widget.ToggleButton;

import com.luck.picture.lib.R;
import com.luck.picture.lib.samsung.DeviceUtils;
import com.luck.picture.lib.samsung.SamSungVideo;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Semaphore;


/**
 * 拍摄视频界面
 * Created by qyhl on 2018/2/22.
 */
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
public class ShootActivity extends AppCompatActivity implements TextureView.SurfaceTextureListener {
    ImageView cameraSwitch;      //切换摄像头
    ShootButton shootBtn;        //开始摄像开关
    ImageView backBtn;           //退出按钮
    RelativeLayout shootInitLayout;      //初始化界面
    ImageView replayBtn;                 //重拍按钮
    ImageView completeBtn;              //完成按钮
    RelativeLayout shootCompleteLayout;    //完成界面
    TextView tips;                    //提示文字
    ToggleButton cameraLight;      //闪光灯开关
    AutoFitTextureView mTextureView;

    //TextureView的宽
    private int mWidth;
    //TextureView的高
    private int mHeight;
    //录制器
    private MediaRecorder mMediaRecorder;
    //处理拍摄的子线程
    private HandlerThread mBackgroundThread;
    //mBackgroundThread子线程处理器
    private Handler mBackgroundHandler;
    //是否正在录制
    private boolean isRecording;

    /*************   camera2   ************/
    //拍摄设配
    private CameraDevice mCameraDevice;
    //预览会话
    private CameraCaptureSession mPreviewSession;
    //当前闪光灯是否开启
    private boolean isLightOn = false;
    //当前是否是前置摄像头
    private boolean isCameraFront = false;
    //后置摄像头ID
    private String mCameraId;
    //前置摄像头ID
    private String mCameraFrontId;
    //预览大小
    private Size mPreviewSize;
    //拍摄大小
    private Size mVideoSize;
    //拍照CaptureRequest
    private CaptureRequest captureRequest;
    //用于获取拍照数据相关
    private ImageReader pictureImageReader;

    private CaptureRequest mCaptureRequest;

    private CameraCharacteristics characteristics;

    private Integer mSensorOrientation;
    //视频录制文件夹
    private final String SAVE_VIDOE_PATH = Environment.getExternalStorageDirectory().getPath() + File.separator + "yunshang" + File.separator + "video";
    private final String SAVE_PIC_PATH = Environment.getExternalStorageDirectory().getPath() + File.separator + "yunshang" + File.separator + "picture";
    //防止退出前关闭摄像机
    private Semaphore mCameraOpenCloseLock = new Semaphore(1);
    //预览视图构造器
    private CaptureRequest.Builder mPreviewBuilder;
    //最大录制时长
    private static  int MAX_RECORD_TIME = 15;
    //
    private String pathName;

    //图片还是视频
    private boolean isVideo;

    private static final int SENSOR_ORIENTATION_DEFAULT_DEGREES = 90;
    private static final int SENSOR_ORIENTATION_INVERSE_DEGREES = 270;
    //拍照方向
    private static final SparseIntArray INVERSE_ORIENTATIONS = new SparseIntArray();
    private static final SparseIntArray DEFAULT_ORIENTATIONS = new SparseIntArray();

    static {
        DEFAULT_ORIENTATIONS.append(Surface.ROTATION_0, 90);
        DEFAULT_ORIENTATIONS.append(Surface.ROTATION_90, 0);
        DEFAULT_ORIENTATIONS.append(Surface.ROTATION_180, 270);
        DEFAULT_ORIENTATIONS.append(Surface.ROTATION_270, 180);
    }

    static {
        INVERSE_ORIENTATIONS.append(Surface.ROTATION_0, 270);
        INVERSE_ORIENTATIONS.append(Surface.ROTATION_90, 180);
        INVERSE_ORIENTATIONS.append(Surface.ROTATION_180, 90);
        INVERSE_ORIENTATIONS.append(Surface.ROTATION_270, 0);
    }


    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);//不显示标题栏
        setContentView(R.layout.activity_shoot_layout);
        //全屏显示
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
        }
        initView();
        setListener();
    }

    /**
     * 初始化界面
     */
    private void initView() {
        cameraSwitch = (ImageView) findViewById(R.id.camera_switch);
        shootBtn = (ShootButton) findViewById(R.id.shoot_btn);
        backBtn = (ImageView) findViewById(R.id.back_btn);
        shootInitLayout = (RelativeLayout) findViewById(R.id.shoot_init_layout);
        replayBtn = (ImageView) findViewById(R.id.replay_btn);
        completeBtn = (ImageView) findViewById(R.id.complete_btn);
        shootCompleteLayout = (RelativeLayout) findViewById(R.id.shoot_complete_layout);
        tips = (TextView) findViewById(R.id.tips);
        cameraLight = (ToggleButton) findViewById(R.id.camera_light);
        cameraSwitch = (ImageView) findViewById(R.id.camera_switch);
        mTextureView = (AutoFitTextureView) findViewById(R.id.textureView);
        MAX_RECORD_TIME = getIntent().getIntExtra("maxTime", 15);
        //显示提示文本
        tips.setVisibility(View.VISIBLE);
        //显示拍摄界面
        shootInitLayout.setVisibility(View.VISIBLE);
        //隐藏拍摄完成界面
        shootCompleteLayout.setVisibility(View.GONE);
        //设置最长拍摄时间
        shootBtn.setLoadingTime(MAX_RECORD_TIME);
    }


    /**
     * 设置监听
     */
    private void setListener() {
        //缩放
        mTextureView.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View view, MotionEvent event) {
                //两指缩放
                changeZoom(event);
                return true;
            }
        });

        //切换摄像头
        cameraSwitch.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                switchCamera();
            }
        });

        //闪光灯
        cameraLight.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                openLight();
            }
        });

        //退出
        backBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                finish();
            }
        });

        //完成
        completeBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent();
                intent.putExtra("isvideo", isVideo);
                intent.putExtra("path", pathName);
                setResult(RESULT_OK, intent);
                finish();
            }
        });

        //重拍
        replayBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                deleteFile();
                tips.setVisibility(View.VISIBLE);
                shootCompleteLayout.setVisibility(View.GONE);
                shootInitLayout.setVisibility(View.VISIBLE);
                startPreview();
            }
        });

        //拍摄按钮监听
        shootBtn.setOnProgressTouchListener(new ShootButton.OnProgressTouchListener() {
            @Override
            public void onClick(ShootButton photoButton) {
                //短按
                if (mPreviewSession != null) {
                    isVideo = false;
                    try {
                        mPreviewSession.capture(captureRequest, null, mBackgroundHandler);
                    } catch (CameraAccessException e) {
                        e.printStackTrace();
                    }
                }
            }

            @Override
            public void onLongClick(ShootButton photoButton) {
                //长按
                if (!isRecording) {
                    isVideo = true;
                    tips.setVisibility(View.GONE);
                    shootCompleteLayout.setVisibility(View.GONE);
                    shootInitLayout.setVisibility(View.VISIBLE);
                    photoButton.start();
                    startRecordingVideo();
                }
            }

            @Override
            public void onLongClickUp(ShootButton photoButton) {
                //长按抬起
                if (isRecording) {
                    if (photoButton.getAnimatorSet() != null) {
                        //onLongClickUp后，倒计时还在继续，在倒计时结束前第二次onLongClick被触发，新建一个倒计时。
                        //为了避免第二次的onLongClick触发第一次计时的onFinish,移除之前的动画监听
                        photoButton.getAnimatorSet().removeAllListeners();
                    }

                    if (shootBtn.getmLoadingTime() - shootBtn.getTime() < 2){
                        Toast.makeText(ShootActivity.this, "录制时间过短", Toast.LENGTH_LONG).show();
                    }else{
                        shootInitLayout.setVisibility(View.GONE);
                        shootCompleteLayout.setVisibility(View.VISIBLE);
                    }

                    stopRecordingVideo();
                }
            }

            @Override
            public void onFinish() {
                //结束
                if (isRecording) {
                    shootInitLayout.setVisibility(View.GONE);
                    shootCompleteLayout.setVisibility(View.VISIBLE);
                    stopRecordingVideo();
                }
            }
        });

    }

    /**
     * **********************************************切换摄像头**************************************
     */
    public void switchCamera() {
        if (mCameraDevice != null) {
            mCameraDevice.close();
            mCameraDevice = null;
        }

        if (isCameraFront) {
            cameraLight.setVisibility(View.VISIBLE);
            isCameraFront = false;
            setupCamera(mWidth, mHeight);
            openCamera(mCameraId);
        } else {
            //前置摄像头没有闪光灯
            cameraLight.setVisibility(View.GONE);
            isCameraFront = true;
            setupCamera(mWidth, mHeight);
            openCamera(mCameraFrontId);
        }
    }

    /**
     * ***************************************打开和关闭闪光灯****************************************
     */
    public void openLight() {
        if (isLightOn) {
            cameraLight.setSelected(false);
            isLightOn = false;
            mPreviewBuilder.set(CaptureRequest.FLASH_MODE,
                    CaptureRequest.FLASH_MODE_OFF);
        } else {
            cameraLight.setSelected(true);
            isLightOn = true;
            mPreviewBuilder.set(CaptureRequest.FLASH_MODE,
                    CaptureRequest.FLASH_MODE_TORCH);
        }

        try {
            if (mPreviewSession != null) {
                mPreviewSession.setRepeatingRequest(mPreviewBuilder.build(), null, mBackgroundHandler);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * *********************************放大或者缩小**********************************
     */
    //手指按下的点为(x1, y1)手指离开屏幕的点为(x2, y2)
    float finger_spacing;
    int zoom_level = 0;
    Rect zoom;

    public void changeZoom(MotionEvent event) {
        try {
            //活动区域宽度和作物区域宽度之比和活动区域高度和作物区域高度之比的最大比率
            float maxZoom = (characteristics.get(CameraCharacteristics.SCALER_AVAILABLE_MAX_DIGITAL_ZOOM)) * 10;
            Rect m = characteristics.get(CameraCharacteristics.SENSOR_INFO_ACTIVE_ARRAY_SIZE);

            int action = event.getAction();
            float current_finger_spacing;
            //判断当前屏幕的手指数
            if (event.getPointerCount() > 1) {
                //计算两个触摸点的距离
                current_finger_spacing = getFingerSpacing(event);

                if (finger_spacing != 0) {
                    if (current_finger_spacing > finger_spacing && maxZoom > zoom_level) {
                        zoom_level++;

                    } else if (current_finger_spacing < finger_spacing && zoom_level > 1) {
                        zoom_level--;
                    }

                    int minW = (int) (m.width() / maxZoom);
                    int minH = (int) (m.height() / maxZoom);
                    int difW = m.width() - minW;
                    int difH = m.height() - minH;
                    int cropW = difW / 100 * (int) zoom_level;
                    int cropH = difH / 100 * (int) zoom_level;
                    cropW -= cropW & 3;
                    cropH -= cropH & 3;
                    zoom = new Rect(cropW, cropH, m.width() - cropW, m.height() - cropH);
                    mPreviewBuilder.set(CaptureRequest.SCALER_CROP_REGION, zoom);
                }
                finger_spacing = current_finger_spacing;
            } else {
                if (action == MotionEvent.ACTION_UP) {
                    //single touch logic,可做点击聚焦操作
                }
            }

            try {
                mPreviewSession.setRepeatingRequest(mPreviewBuilder.build(), new CameraCaptureSession.CaptureCallback() {
                            @Override
                            public void onCaptureCompleted(@NonNull CameraCaptureSession session, @NonNull CaptureRequest request, @NonNull TotalCaptureResult result) {
                                super.onCaptureCompleted(session, request, result);
                            }
                        },
                        null);
            } catch (Exception e) {
                Log.e("error_shoot", e.getMessage() == null ? "null" : e.getMessage());
                e.printStackTrace();
            }
        } catch (Exception e) {
            Log.e("error_shoot", e.getMessage() == null ? "null" : e.getMessage());
            throw new RuntimeException("can not access camera.", e);
        }
    }

    //计算两个触摸点的距离
    private float getFingerSpacing(MotionEvent event) {
        float x = event.getX(0) - event.getX(1);
        float y = event.getY(0) - event.getY(1);
        return (float) Math.sqrt(x * x + y * y);
    }


    /**
     * 相机状态改变的回调函数
     */
    private CameraDevice.StateCallback mStateCallback = new CameraDevice.StateCallback() {
        @Override
        public void onOpened(@NonNull CameraDevice camera) {
            mCameraDevice = camera;
            startPreview();
            mCameraOpenCloseLock.release();
            if (null != mTextureView) {
                configureTransform(mTextureView.getWidth(), mTextureView.getHeight());
            }
        }

        @Override
        public void onDisconnected(@NonNull CameraDevice camera) {
            mCameraOpenCloseLock.release();
            camera.close();
            mCameraDevice = null;
        }

        @Override
        public void onError(@NonNull CameraDevice camera, int error) {
            Log.e("error_shoot", "errorCode:" + error);
            mCameraOpenCloseLock.release();
            camera.close();
            mCameraDevice = null;
            finish();
        }
    };

    /**
     * SurfaceTexture监听器
     */
    @Override
    public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
        this.mWidth = width;
        this.mHeight = height;
        //打开后置摄像头
        setupCamera(mWidth, mHeight);
        openCamera(mCameraId);
    }

    @Override
    public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
        configureTransform(mWidth, mHeight);
    }

    @Override
    public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
        if (mCameraDevice != null) {
            closeCamera();
            mCameraDevice = null;
        }
        return false;
    }

    @Override
    public void onSurfaceTextureUpdated(SurfaceTexture surface) {

    }

    /***************************************** 生命周期  *********************************************************/
    @Override
    protected void onResume() {
        super.onResume();
        startBackgroundThread();
        if (mTextureView.isAvailable()) {
            setupCamera(mTextureView.getWidth(), mTextureView.getHeight());
            openCamera(mCameraId);
        } else {
            mTextureView.setSurfaceTextureListener(this);
        }

        //每次开启预览缩放重置为正常状态
        if (zoom != null) {
            zoom.setEmpty();
            zoom_level = 0;
        }

        //每次开启预览默认闪光灯没开启
        isLightOn = false;
        cameraLight.setSelected(false);

        //每次开启预览默认是后置摄像头
        isCameraFront = false;
    }

    @Override
    public void onPause() {
        closeCamera();
        stopBackgroundThread();
        super.onPause();
    }

    /**
     * 开启线程
     */
    private void startBackgroundThread() {
        mBackgroundThread = new HandlerThread("CameraBackground");
        mBackgroundThread.start();
        mBackgroundHandler = new Handler(mBackgroundThread.getLooper());
    }

    /**
     * 停止线程
     */
    private void stopBackgroundThread() {
        mBackgroundThread.quitSafely();
        try {
            mBackgroundThread.join();
            mBackgroundThread = null;
            mBackgroundHandler = null;
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    /**
     * 开启照相机
     */
    private void openCamera(String cameraId) {
        //获取摄像头的管理者CameraManager
        CameraManager manager = (CameraManager) getSystemService(Context.CAMERA_SERVICE);
        //检查权限
        try {
            if (ActivityCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
                return;
            }
            //打开相机，第一个参数指示打开哪个摄像头，第二个参数stateCallback为相机的状态回调接口，第三个参数用来确定Callback在哪个线程执行，为null的话就在当前线程执行
            manager.openCamera(cameraId, mStateCallback, null);
        } catch (CameraAccessException e) {
            Log.e("error_shoot", e.getMessage());
            Toast.makeText(this, "无法连接到拍摄设备", Toast.LENGTH_SHORT).show();
        }
    }

    /**
     * 设置照相机
     */
    private void setupCamera(int width, int height) {
        //获取摄像头的管理者CameraManager
        CameraManager manager = (CameraManager) getSystemService(Context.CAMERA_SERVICE);
        try {
            //0表示后置摄像头,1表示前置摄像头
            mCameraId = manager.getCameraIdList()[0];
            mCameraFrontId = manager.getCameraIdList()[1];

            //前置摄像头和后置摄像头的参数属性不同，所以这里要做下判断
            if (isCameraFront) {
                characteristics = manager.getCameraCharacteristics(mCameraFrontId);
            } else {
                characteristics = manager.getCameraCharacteristics(mCameraId);
            }

            //获取StreamConfigurationMap，它是管理摄像头支持的所有输出格式和尺寸
            StreamConfigurationMap map = characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
            mSensorOrientation = characteristics.get(CameraCharacteristics.SENSOR_ORIENTATION);

            if (map == null) {
                throw new RuntimeException("Cannot get available preview/video sizes");
            }
            mVideoSize = CameraUtil.chooseVideoSize(map.getOutputSizes(MediaRecorder.class));
            mPreviewSize = CameraUtil.getMinPreSize(map.getOutputSizes(SurfaceTexture.class), width, height, 1000);
            int orientation = getResources().getConfiguration().orientation;
            if (orientation == Configuration.ORIENTATION_LANDSCAPE) {
                mTextureView.setAspectRatio(mPreviewSize.getWidth(), mPreviewSize.getHeight());
            } else {
                mTextureView.setAspectRatio(mPreviewSize.getHeight(), mPreviewSize.getWidth());
            }
            configureTransform(width, height);
            mMediaRecorder = new MediaRecorder();
        } catch (CameraAccessException e) {
            Log.e("error_shoot", e.getMessage());
            Toast.makeText(this, "无法获取到拍摄设备", Toast.LENGTH_SHORT).show();
        } catch (NullPointerException e) {
            // Currently an NPE is thrown when the Camera2API is used but not supported on the
            // device this code runs.
            Log.e("error_shoot", e.getMessage());
        }

    }

    /**
     * 关闭照相机
     */
    private void closeCamera() {
        try {
            mCameraOpenCloseLock.acquire();
            closePreviewSession();
            if (null != mCameraDevice) {
                mCameraDevice.close();
                mCameraDevice = null;
            }
            if (null != mMediaRecorder) {
                mMediaRecorder.release();
                mMediaRecorder = null;
            }
        } catch (InterruptedException e) {
            Log.e("error_shoot", e.getMessage());
            throw new RuntimeException("Interrupted while trying to lock camera closing.");
        } finally {
            mCameraOpenCloseLock.release();
        }
    }

    /**
     * 开启预览
     */
    private void startPreview() {
        if (null == mCameraDevice || !mTextureView.isAvailable() || null == mPreviewSize) {
            return;
        }
        try {
            closePreviewSession();
            List<Surface> surfaces = new ArrayList<>();
            SurfaceTexture texture = mTextureView.getSurfaceTexture();
            assert texture != null;
            texture.setDefaultBufferSize(mPreviewSize.getWidth(), mPreviewSize.getHeight());
            mPreviewBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);

            Surface previewSurface = new Surface(texture);
            mPreviewBuilder.addTarget(previewSurface);
            surfaces.add(previewSurface);

            //----------拍照输出
            final CaptureRequest.Builder captureRequestBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);
            captureRequestBuilder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);
            captureRequestBuilder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH);
            int rotation = getWindowManager().getDefaultDisplay().getRotation();
            switch (mSensorOrientation) {
                case SENSOR_ORIENTATION_DEFAULT_DEGREES:
                    captureRequestBuilder.set(CaptureRequest.JPEG_ORIENTATION, DEFAULT_ORIENTATIONS.get(rotation));
                    break;
                case SENSOR_ORIENTATION_INVERSE_DEGREES:
                    captureRequestBuilder.set(CaptureRequest.JPEG_ORIENTATION, INVERSE_ORIENTATIONS.get(rotation));
                    break;
                default:
                    break;
            }
            Surface pictureSurface = getPictureImageReaderSurface();
            captureRequestBuilder.addTarget(pictureSurface);
            surfaces.add(pictureSurface);
            captureRequest = captureRequestBuilder.build();
            //-------------------------

            mCameraDevice.createCaptureSession(surfaces, new CameraCaptureSession.StateCallback() {
                @Override
                public void onConfigured(@NonNull CameraCaptureSession session) {
                    try {
                        //创建捕获请求
                        mCaptureRequest = mPreviewBuilder.build();
                        mPreviewSession = session;
                        updatePreview();
                        //不停的发送获取图像请求，完成连续预览
                        mPreviewSession.setRepeatingRequest(mCaptureRequest, null, mBackgroundHandler);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }

                @Override
                public void onConfigureFailed(@NonNull CameraCaptureSession session) {
                    Activity activity = ShootActivity.this;
                    if (null != activity) {
                        Toast.makeText(activity, "Failed", Toast.LENGTH_SHORT).show();
                    }
                }
            }, mBackgroundHandler);
        } catch (CameraAccessException e) {
            e.printStackTrace();
        }
    }

    private Surface getPictureImageReaderSurface() {
        pictureImageReader = ImageReader.newInstance(mPreviewSize.getWidth(), mPreviewSize.getHeight(), ImageFormat.JPEG, 2);
        pictureImageReader.setOnImageAvailableListener(new ImageReader.OnImageAvailableListener() {
            @Override
            public void onImageAvailable(ImageReader reader) {
                Image image = reader.acquireNextImage();
                ByteBuffer byteBuffer = image.getPlanes()[0].getBuffer();
                byte[] bytes = new byte[byteBuffer.remaining()];
                byteBuffer.get(bytes);
                image.close();
                saveImage(bytes);
            }
        }, mBackgroundHandler);
        return pictureImageReader.getSurface();
    }

    private void saveImage(byte[] bytes) {
        BufferedOutputStream output;
        try {
            output = new BufferedOutputStream(new FileOutputStream(getVideoFilePath(SAVE_PIC_PATH, ".jpg")));
        } catch (FileNotFoundException e) {
            e.printStackTrace();
            return;
        }
        if (isCameraFront) {
            Bitmap newBitmap = mirror(BitmapFactory.decodeByteArray(bytes, 0, bytes.length));
            newBitmap.compress(Bitmap.CompressFormat.JPEG, 100, output);
            newBitmap.recycle();
        } else {
            try {
                output.write(bytes);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        try {
            output.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        closePreviewSession();
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                Toast.makeText(ShootActivity.this, "录制时间过短", Toast.LENGTH_LONG).show();
                deleteFile();
                tips.setVisibility(View.VISIBLE);
                shootCompleteLayout.setVisibility(View.GONE);
                shootInitLayout.setVisibility(View.VISIBLE);
                startPreview();
//                shootInitLayout.setVisibility(View.GONE);
//                shootCompleteLayout.setVisibility(View.VISIBLE);
            }
        });
    }

    private Bitmap mirror(Bitmap temp) {
        Matrix m = new Matrix();
        m.postScale(-1, 1);
        Bitmap newBitmap = Bitmap.createBitmap(temp, 0, 0, temp.getWidth(), temp.getHeight(), m, true);
        temp.recycle();
        return newBitmap;
    }

    /**
     * 刷新预览
     */
    private void updatePreview() {
        if (null == mCameraDevice) {
            return;
        }
        try {
            setUpCaptureRequestBuilder(mPreviewBuilder);
            HandlerThread thread = new HandlerThread("CameraPreview");
            thread.start();
            mPreviewSession.setRepeatingRequest(mPreviewBuilder.build(), null, mBackgroundHandler);
        } catch (CameraAccessException e) {
            e.printStackTrace();
        }
    }

    private void setUpCaptureRequestBuilder(CaptureRequest.Builder builder) {
        builder.set(CaptureRequest.CONTROL_MODE, CameraMetadata.CONTROL_MODE_AUTO);
    }

    /**
     * 屏幕横竖屏转换
     *
     * @param viewWidth
     * @param viewHeight
     */
    private void configureTransform(int viewWidth, int viewHeight) {
        Activity activity = ShootActivity.this;
        if (null == mTextureView || null == mPreviewSize || null == activity) {
            return;
        }
        int rotation = activity.getWindowManager().getDefaultDisplay().getRotation();
        Matrix matrix = new Matrix();
        RectF viewRect = new RectF(0, 0, viewWidth, viewHeight);
        RectF bufferRect = new RectF(0, 0, mPreviewSize.getHeight(), mPreviewSize.getWidth());
        float centerX = viewRect.centerX();
        float centerY = viewRect.centerY();
        if (Surface.ROTATION_90 == rotation || Surface.ROTATION_270 == rotation) {
            bufferRect.offset(centerX - bufferRect.centerX(), centerY - bufferRect.centerY());
            matrix.setRectToRect(viewRect, bufferRect, Matrix.ScaleToFit.FILL);
            float scale = Math.max(
                    (float) viewHeight / mPreviewSize.getHeight(),
                    (float) viewWidth / mPreviewSize.getWidth());
            matrix.postScale(scale, scale, centerX, centerY);
            matrix.postRotate(90 * (rotation - 2), centerX, centerY);
        }
        mTextureView.setTransform(matrix);
    }

    /**
     * 设置录制配置
     *
     * @throws IOException
     */
    private void setUpMediaRecorder() throws IOException {
        mMediaRecorder.reset();
        // 这两项需要放在setOutputFormat之前
        mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
        mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.SURFACE);

        mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);

        mMediaRecorder.setOutputFile(getVideoFilePath(SAVE_VIDOE_PATH, ".mp4"));
        mMediaRecorder.setVideoEncodingBitRate(1024 * 1024);
        mMediaRecorder.setVideoFrameRate(20);//这个没用，帧率会根据不同手机自行调整
        mMediaRecorder.setVideoSize(mPreviewSize.getWidth(), mPreviewSize.getHeight());

        // 这两项需要放在setOutputFormat之后
        mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);
        mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);

        int rotation = getWindowManager().getDefaultDisplay().getRotation();
        switch (mSensorOrientation) {
            case SENSOR_ORIENTATION_DEFAULT_DEGREES:
                mMediaRecorder.setOrientationHint(DEFAULT_ORIENTATIONS.get(rotation));
                break;
            case SENSOR_ORIENTATION_INVERSE_DEGREES:
                mMediaRecorder.setOrientationHint(INVERSE_ORIENTATIONS.get(rotation));
                break;
            default:
                break;
        }
        mMediaRecorder.prepare();
    }


    /**
     * 获取文件路径
     *
     * @return
     */
    private String getVideoFilePath(String path, String suffix) {
        File file = new File(path);
        if (!file.exists()) {
            file.mkdirs();
        }
        pathName = path + File.separator + "qz" + System.currentTimeMillis() + suffix;
        return pathName;
    }

    /**
     * 删除文件
     */
    private void deleteFile() {
        if (pathName != null) {
            File file = new File(pathName);
            if (file.exists() && file.isFile()) {
                file.delete();
            }
        }
    }

    /**
     * 开始录制
     */
    private void startRecordingVideo() {
        if (null == mCameraDevice || !mTextureView.isAvailable() || null == mPreviewSize) {
            return;
        }
        try {
            closePreviewSession();
            setUpMediaRecorder();
            SurfaceTexture texture = mTextureView.getSurfaceTexture();
            assert texture != null;
            texture.setDefaultBufferSize(mPreviewSize.getWidth(), mPreviewSize.getHeight());
            mPreviewBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_RECORD);
            List<Surface> surfaces = new ArrayList<>();

            // Set up Surface for the camera preview
            Surface previewSurface = new Surface(texture);
            surfaces.add(previewSurface);
            mPreviewBuilder.addTarget(previewSurface);

            // Set up Surface for the MediaRecorder
            Surface recorderSurface = mMediaRecorder.getSurface();
            surfaces.add(recorderSurface);
            mPreviewBuilder.addTarget(recorderSurface);

            //判断预览之前有没有开闪光灯
            if (isLightOn) {
                mPreviewBuilder.set(CaptureRequest.FLASH_MODE, CaptureRequest.FLASH_MODE_TORCH);
            } else {
                mPreviewBuilder.set(CaptureRequest.FLASH_MODE, CaptureRequest.FLASH_MODE_OFF);
            }

            //保持当前的缩放比例
            mPreviewBuilder.set(CaptureRequest.SCALER_CROP_REGION, zoom);

            // Start a capture session
            // Once the session starts, we can update the UI and start recording
            mCameraDevice.createCaptureSession(surfaces, new CameraCaptureSession.StateCallback() {

                @Override
                public void onConfigured(@NonNull CameraCaptureSession cameraCaptureSession) {
                    mPreviewSession = cameraCaptureSession;
                    updatePreview();//设置反复捕获数据的请求，这样预览界面就会一直有数据显示
                    runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            // UI
                            isRecording = true;
                            // Start recording
                            mMediaRecorder.start();
                        }
                    });
                }

                @Override
                public void onConfigureFailed(@NonNull CameraCaptureSession cameraCaptureSession) {
                    Toast.makeText(ShootActivity.this, "Failed", Toast.LENGTH_SHORT).show();
                }
            }, mBackgroundHandler);
        } catch (CameraAccessException | IOException e) {
            Log.e("@@@@", e.toString() + "::::" + e.getMessage());
            e.printStackTrace();
        }

    }


    /**
     * 停止录制
     */
    private void stopRecordingVideo() {
        // UI
        isRecording = false;
        // Stop recording
        try {
            mPreviewSession.stopRepeating();
            mMediaRecorder.stop();
            mMediaRecorder.reset();
            if (DeviceUtils.isSamsung()) {
                String name = SAVE_VIDOE_PATH + File.separator + "qz" + (System.currentTimeMillis() + 1) + ".mp4";
                SamSungVideo samSungVideo = new SamSungVideo(pathName, name);
                samSungVideo.muxerMedia();
                pathName = name;
            }
        } catch (Exception e) {
            Log.e("error_shoot", e.getMessage() == null ? "null" : e.getMessage());
            Toast.makeText(this, "录制时间过短", Toast.LENGTH_LONG).show();
            tips.setVisibility(View.VISIBLE);
            shootCompleteLayout.setVisibility(View.GONE);
            shootInitLayout.setVisibility(View.VISIBLE);
            deleteFile();
        }
        startPreview();
    }

    /**
     * **************************************清除操作************************************************
     */
    private void closePreviewSession() {
        if (mPreviewSession != null) {
            mPreviewSession.close();
            mPreviewSession = null;
        }
        if (pictureImageReader != null) {
            pictureImageReader.close();
            pictureImageReader = null;
        }
    }

}
